home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / 3DGPL.ZIP / 3DGPL / TEXT / 4.TXT < prev   
Text File  |  1995-06-22  |  29KB  |  741 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.                                2-D clipping.
  8.                               ---------------
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.                                          "Don't discount flying pigs before
  16.                                          you have good air defense."
  17.                                          -- jvh@clinet.fi
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24. Screen boundaries clipping.
  25. ---------------------------
  26. Throughout the last chapter we've assumed that primitives we were rendering
  27. are completely within the screen boundaries. This is something we can't
  28. really guarantee. The worst thing- if we would try using those functions
  29. to render an element outside the screen, they won't much complain and
  30. would most likely try accessing memory outside the colourmap's allocated
  31. space. And I guess: segmentation fault, core dumped is hardly most
  32. graceful way to exit a program. So we don't have another choice but
  33. to guarantee rendering algorithms that the element passed is indeed
  34. inside the screen.
  35.  
  36.  
  37.  
  38. A dot.
  39. ------
  40. Clipping looks trivial in case of a dot, we just have to add few
  41. comparisons checking if the coordinates are in the screen range and
  42. proceed only if that is the case:
  43.  
  44. void G_dot(int x,int y,unsigned char colour)
  45. {
  46.  if( (x>=0)&&(x<HW_SCREEN_X_SIZE) && (y>=0)&&(y<HW_SCREEN_Y_SIZE) )
  47.  {
  48.   G_buffer[y*HW_SCREEN_X_SIZE+x]=colour;
  49.  }
  50. }
  51.  
  52. And of course there if we are always clipping to a rectangular with a
  53. diagonal (0,0-something_x,something_y) we can do it with just 2
  54. comparisons instead of 4, just by making sure x and y passed are
  55. considered by unsigned comparisons, (negative numbers after all 
  56. would be thought of as just very big positive).
  57.  
  58.  
  59. A line.
  60. -------
  61. We can extend above method for line and check every time before
  62. plotting a dot whether it is within the boundaries. Unfortunately by
  63. doing that we push up the complexity of the code within the loop.
  64. And moreover our optimized line routine work with addresses of
  65. points within the colourmap rather then with the coordinates. What
  66. we would have to construct is a function that would take in
  67. arbitrary coordinates of some line and return back the coordinates
  68. of a line's part which is within the screen boundaries. This
  69. process is called clipping. The clipping routine must basically
  70. find coordinates of an intersection point between the line and
  71. some of the screen edges.
  72.  
  73.                        * A
  74.                         \\
  75.                          \ \
  76.                           \  \I1
  77.                            \ +-o---------------- Y=0
  78.                             \|   \
  79.                            I2o     \
  80.                              |\      * B
  81.                              | *C
  82.                              |
  83.                             X=0
  84.  
  85.                           pic 4.1
  86.  
  87. The problem is that we are not sure on what edge the intersection
  88. point lies, for example in the picture above line A-B intersects
  89. screen at the edge Y==0, whereas line A-C intersects it at the
  90. edge X==0. Generally we can avoid thinking where the intersection
  91. is located by consecutive clipping a line against first, say,
  92. vertical boundaries limits and then horizontal:
  93.  
  94.                         * A  |
  95.                           \  |
  96.                             \oI1
  97.                              |\
  98.                        ------+--o--------------- Y=0
  99.           * G                | I2 \
  100.            \                 |      \
  101.              \               |        * B     *E
  102.               *H        C*---o--*D             \
  103.                              |                  *F
  104.                              |
  105.                             X=0
  106.  
  107.                           pic 4.2
  108.  
  109. In the example above after first call to clipping routine line
  110. A-B would become I1-B, after the second it would assume the
  111. final acceptable form I2-B. It can be seen also that some lines
  112. going through this clipping method won't actually be clipped at
  113. all (E-F) some would be clipped just once (C-D), some twice
  114. (A-B) and finally some would be completely clipped, that is,
  115. would be totally outside the screen area (G-H). Now, how to find
  116. an intersection point? obviously it is not a very complicated
  117. case of solving similar triangles:
  118.  
  119.  
  120.                           |
  121.               (x1,y1) *   |
  122.                       | \ |
  123.                       |   * (xm,ym)
  124.                       |   | \
  125.                       +---|---* (x2,y2)
  126.                           |
  127.  
  128.                         pic 4.3
  129.  
  130.  
  131.         y2-ym     y2-y1                    (y2-y1)*(x2-xm)
  132.        ------- = -------   =>   ym = y2 - -----------------
  133.         x2-xm     x2-x1                         x2-x1
  134.  
  135.  
  136. but this method involves multiplications and divisions, so
  137. beholding to our tradition let's try to avoid it. The alternative
  138. method is using binary search:
  139.  
  140.  
  141.                       A(-3,1)
  142.                         *    |
  143.                          \   |
  144.                      (-1,3)* |
  145.                              o I(0,?)
  146.                              | \
  147.                              |   * B(1,5)
  148.                              |
  149.                             X=0
  150.  
  151.                           pic 4.4
  152.  
  153.  
  154. Let's see how it works on a simple example: suppose we have
  155. to clip a line A(-3,1)-B(1,5) by an edge X=0 , we have to
  156. find Y of the intersection point. let's find midpoint of
  157. the line A-B:
  158.  
  159.                    Ax+Bx              Ay+By
  160.              midx=-------       midy=-------
  161.                      2                  2
  162.  
  163.              midx=(-3+1)/2=-1   midy=(1+5)/2=3
  164.  
  165. Now, let's see where the boundary lies with respect to the midpoint?
  166. It is still to the right of it, so of two lines A-MidPoint MidPoint-B,
  167. edge intersects MidPoint-B. Let's rename MidPoint into A and start
  168. the midpoint search over again:
  169.  
  170.              midx=(-1+1)/2=0    midy=(3+5)/2=4
  171.  
  172. Here, the intersection came precisely onto the edge. So midy is the
  173. Y coordinate of Intersection point we were looking for. It appears
  174. that this method involve a lot of calculations, but they are all
  175. very cheap, just an addition and division by two (which is
  176. actually a 1 bit right shift). Practice shows binary search works
  177. indeed faster then calculation resulting from solving similar
  178. triangles.
  179.  
  180. When dealing with divisions performed by shits however, one has to be 
  181. aware of truncation problems that might arise. Since -1>>1=-1 that means 
  182. that if we would try to use algorithm described above to clipp (-1,y1)-(0,y2) 
  183. line by X==0 boundary chances are we would loop forever, at each iteration 
  184. finding that -1>>1 is still -1. (and O(for ever) is hardly, the time 
  185. complexity contributing towards high frame-rate). As in the code below 
  186. this situation should be thought of.
  187.  
  188. Let's create a function which would perform clipping against
  189. two vertical screen edges: that is C_X_CLIPPING_MIN and C_X_CLIPPING_MAX.
  190.  
  191.  
  192.  
  193. int C_line_x_clipping(int **vertex1,int **vertex2,int dimension)
  194. {
  195.  register int i;
  196.  register int whereto;
  197.  register int *l,*r,*m,*t;                  /* left right and midle and tmp */
  198.  static int g_store0[C_MAX_DIMENSIONS];     /* static stores for clipped vxes */
  199.  static int g_store1[C_MAX_DIMENSIONS];
  200.  static int g_store2[C_MAX_DIMENSIONS];
  201.  static int g_store3[C_MAX_DIMENSIONS];
  202.  static int g_store4[C_MAX_DIMENSIONS];
  203.  static int g_store5[C_MAX_DIMENSIONS];
  204.  int **vmn,**vmx;                           /* so that *vmn[0] < *vmx[0] */
  205.  int swap;                                  /* we coordinates swaped? */
  206.  
  207.  C_2D_clipping=0;                           /* default no clipping yet */
  208.  
  209.  if((*vertex1)[0]<(*vertex2)[0])
  210.  { swap=0; vmn=vertex1; vmx=vertex2; }      /* so that *vmn[0] < *vmx[0] */
  211.  else
  212.  { swap=1; vmn=vertex2; vmx=vertex1; }
  213.  
  214.  if(((*vmn)[0]>C_X_CLIPPING_MAX)||((*vmx)[0]<C_X_CLIPPING_MIN)) return(0);
  215.  else
  216.  {
  217.   if((*vmn)[0]<=C_X_CLIPPING_MIN)           /* clipping */
  218.   {
  219.    HW_copy_int(*vmn,l=g_store0,dimension);  /* copying old vertixes */
  220.    HW_copy_int(*vmx,m=g_store1,dimension);
  221.    r=g_store2;                              /* let middle be there */
  222.  
  223.    whereto=0;
  224.    while(m[0]!=C_X_CLIPPING_MIN)
  225.    {
  226.     if(whereto==1) { t=l; l=m; m=t; }
  227.     else           { t=r; r=m; m=t; }
  228.     for(i=0;i<dimension;i++) m[i]=(l[i]+r[i])>>1;
  229.     whereto=m[0]<C_X_CLIPPING_MIN;
  230.    }
  231.    *vmn=m;                                  /* that is why m[] is static */
  232.    C_2D_clipping=swap^1;
  233.   }
  234.  
  235.   if((*vmx)[0]>=C_X_CLIPPING_MAX)           /* clipping */
  236.   {
  237.    HW_copy_int(*vmn,l=g_store3,dimension);  /* copying old vertixes */
  238.    HW_copy_int(*vmx,m=g_store4,dimension);
  239.    r=g_store5;                              /* let middle be here */
  240.  
  241.    whereto=0;
  242.    while(m[0]!=C_X_CLIPPING_MAX)
  243.    {
  244.     if(whereto==1) { t=l; l=m; m=t; }
  245.     else           { t=r; r=m; m=t; }
  246.     for(i=0;i<dimension;i++) m[i]=(l[i]+r[i])>>1;
  247.     whereto=m[0]<C_X_CLIPPING_MAX;
  248.    }
  249.    *vmx=m;                                  /* that is why m[] is static */
  250.    C_2D_clipping|=swap&1;
  251.   }
  252.  }
  253.  return(1);                                 /* partialy or not clipped */
  254. }
  255.  
  256.  
  257.  
  258. The return value of this function is zero if line is completely
  259. clipped otherwise it is 1. The purpose of global C_2D_clipping variable
  260. would become clear when we would be talking about polygon clipping.
  261. As to the Y clipping we can either modify the above code to
  262. do both functions or just duplicate most of the code changing few
  263. things, like constants names ( C_Y_CLIP... instead of C_X_CLIPP...)
  264. and indexes of clipped variable ( 1 instead of 0).
  265.  
  266. As you can see this code is generic enough to allow clipping of
  267. N-dimensional lines ( so that to allow for X Y Z Colour Intensity etc. to
  268. be processed at the same time). To do it effectively static arrays are
  269. being set to keep temporary left (l) middle (m) and right (r) N-tuples.
  270. Whenever making decision which segment to take for the next iteration
  271. we can just swap pointers, so that array keeping coordinate of segment
  272. being discarded could be set to accept middle point at the next iteration.
  273.  
  274.             <-----------  m
  275.          l  ----------->                   r
  276.          |                |                |
  277.          v                v                v
  278.          +---------+      +---------+      +---------+
  279.          |x,y,z... |      |x,y,z... |      |x,y,z... |
  280.          +---------+      +---------+      +---------+
  281.  
  282.                             pic 4.5
  283.  
  284. This is being done so that at every iteration only pointers to
  285. actual data are moved not the data itself. (The point I am trying to
  286. make: (and I am sure everybody knows that, just a bit of reinforcement)
  287. it's ok to physically copy small amounts of data, but when we have a lot
  288. of it, it is better to move pointers instead)
  289.  
  290.  
  291. Let's insert calls to clipping function into the G_line routine:
  292.  
  293.  
  294.                                   ...
  295.                                   ...
  296.  
  297.  v1=vertex1;
  298.  v2=vertex2;
  299.  
  300.  if(C_line_x_clipping(&v1,&v2,2))           /* horizontal clipping */
  301.  {
  302.   if(C_line_y_clipping(&v1,&v2,2))          /* vertical clipping */
  303.   {
  304.    dx=v2[0]-v1[0]; dy=v2[1]-v1[1];          /* ranges */
  305.  
  306.                                   ...
  307.                                   ...
  308.  
  309.  
  310. So, whenever line is completely clipped we wouldn't go any further
  311. in the rasterization function.
  312.  
  313.  
  314.  
  315. A polygon.
  316. ----------
  317. Now, remembering that we render polygon by scanning it's edges
  318. using rasterization function pretty much like the one above, we
  319. may think that adding clipping calls into GI_scan would solve our
  320. problem with polygon clipping, unfortunately, it is only half true
  321. (literary half true). Lets consider pictures pic 4.6 and 4.7:
  322.  
  323.  
  324.                    B                          * B
  325.                  | *====                    I/
  326.                  |/====                -----*------
  327.                 I*======                   /======
  328.                 /|??????                  /========
  329.                / |?????                  /========
  330.              A*  |??????               A*==========
  331.  
  332.  
  333.                 pic 4.6                   pic 4.7
  334.  
  335. In the cases above edge A-B contribute to the left side of the
  336. polygon, clipping present no problem for case on pic 4.7. Clipped
  337. part I-B of the edge can be discarded since there's nothing to
  338. form outside the screen. On the other hand in the case on
  339. pic 4.6 we can't simply discard clipped part A-I since we would
  340. loose left boundary of all horizontal lines marked "???". The
  341. observation we can make is that polygon, being scanned edge at
  342. a time, may not be clipped against horizontal boundaries but
  343. must be clipped against vertical, this way the code within GI_scan
  344. would look like:
  345.  
  346.                                   ...
  347.                                   ...
  348.  
  349.  v1=edges; edges+=skip; v2=edges;           /* length ints in each */
  350.  
  351.  if(C_line_y_clipping(&v1,&v2,dimension))   /* vertical clipping */
  352.  {
  353.   dx=*v2++; dy=*v2++;                       /* extracting 2-D coordinates */
  354.   x=*v1++; y=*v1++;                         /* v2/v1 point remaining dim-2 */
  355.  
  356.                                   ...
  357.                                   ...
  358.  
  359.  
  360. Creating a vertically clipped polygon on the other hand is a bit
  361. more complicated. The problem is that the clipped polygon may
  362. have different from the original one number of edges. let's
  363. consider the situation on the pic 4.8:
  364.  
  365.                                                /* 3
  366.                      |                      | / |
  367.                      |5'                    |/  |
  368.                   5*-*-----*6               *   |
  369.                   /  |      \              /|2''|
  370.                 4*   |       *1         2 * |   |
  371.                   \  |      /              \|   |
  372.                   3*-*-----*2               *\  |
  373.                      |3'                    |2'\* 1
  374.  
  375.  
  376.                    pic 4.8                pic 4.9
  377.  
  378. It can be seen that original polygon has 6 edges which becomes 5
  379. after clipping. Some other polygon pic 4.9 can have 1 more edge
  380. after clipping. It is obvious that we would have to create a
  381. temporary structure to hold the clipped polygon. Now, we know how
  382. to clip a single edge, let's try to find pattern how clipped
  383. edges compose clipped polygon. Let's be considering clipping
  384. against a single boundary, say X==0. it is obvious that if an edge
  385. is completely outside it's vertexes won't be present in the new
  386. polygon. On the other hand if an edge is within the boundary
  387. both points would be present. Any point on the intersection
  388. line would be present too. One more consideration is that each
  389. point in the polygon belong to two edges, so when the edge is
  390. not clipped we may put into the new structure just the second
  391. point assuming that the first one is already taken care of when
  392. we were processing previous edge.
  393.  
  394. Let's list the patterns:
  395.  
  396. (1) If edge is not clipped or the second point is clipped put into
  397.     new structure just the second point;
  398.  
  399. (2) When first point is changed or both are changed put both;
  400.  
  401. (3) When both are outside put none.
  402.  
  403. Surprisingly enough this algorithm doesn't have to be changed
  404. when we consider simultaneous clipping against two parallel
  405. boundaries:
  406.  
  407.  
  408.                              | *-----*1|
  409.                              |/5      \|
  410.                            4'*         *2'
  411.                             /|         |\
  412.                           4* |         | \
  413.                            | |         |  \
  414.                            *-*---------*---*2
  415.                            3 |3'       |2''
  416.                              |         |
  417.  
  418.                                pic 4.10
  419.  
  420. edge 1-2   Second point clipped - pattern (1)  putting in 2'
  421. edge 2-3   Both points changed  - pattern (2)  putting in 2'' and 3'
  422. edge 3-4   Both points outside  - pattern (3)  ignoring
  423. edge 4-5   First point clipped  - pattern (2)  putting in 4'  and 5
  424. edge 5-1   No clipping          - pattern (1)  putting in 1
  425.  
  426. The result is: 2'-2''-3'-4'-5-1 just looking at the picture assures
  427. us that what we got is indeed right. Now finally the purpose of
  428. C_2D_clipping variable being set in C_line_x_clipping must be clear.
  429. It would be set to 1 whenever first or both points were changed,
  430. and would be 0 if none or just second one were changed. Knowing
  431. this all let's write some code:
  432.  
  433.  
  434.  
  435. int C_polygon_x_clipping(register int *from,register int *to,
  436.                          int dimension,int length
  437.                         )
  438. {
  439.  register int i;
  440.  int *v1,*v2,new_lng=0;
  441.  int *first_vrtx=to;                        /* begining of the source */
  442.  
  443.  for(i=0;i<length;i++)                      /* for all edges */
  444.  {
  445.   v1=from; from+=dimension; v2=from;        /* taking two vertexes */
  446.  
  447.   if(C_line_x_clipping(&v1,&v2,dimension))  /* clipping */
  448.   {
  449.    if(C_2D_clipping)                        /* depends which one was clipped */
  450.    {
  451.     HW_copy_int(v1,to,dimension); to+=dimension;
  452.     HW_copy_int(v2,to,dimension); to+=dimension;
  453.     new_lng+=2;                             /* first point clipped */
  454.    }
  455.    else
  456.    {
  457.     HW_copy_int(v2,to,dimension); to+=dimension;
  458.     new_lng++;                              /* second point clipped */
  459.    }
  460.   }
  461.  }
  462.  HW_copy_int(first_vrtx,to,dimension);      /* looping the polygon vertexes */
  463.  
  464.  return(new_lng);
  465. }
  466.  
  467.  
  468.  
  469.  
  470. Again the way we represent the polygon the very first point has to
  471. be the last too since every point belong to two edges, and we can
  472. have a pointer to a new edge by just advancing it by "dimension" of
  473. a single vertex in the list of polygon vertices.
  474.  
  475.  
  476. View plane clipping.
  477. --------------------
  478. As discussed before if we want to do perspective transformation we
  479. have to make sure we are actually applying it to something that we know
  480. produces a valid result, hence there should be no points with negative
  481. or zero Z coordinates. Zero would produce divide errors, Negative once
  482. would appear flipped over. There is another good reason to clip out 
  483. vertices with negative Z, we just can't see things which are behind 
  484. us (at least majority of us can't).
  485.  
  486. The technique we would be using is just an expansion of 2-D clipping
  487. that was used to make sure 2-D primitives fit physical screen before
  488. rendering. As before, we can find the intersection point from solving
  489. similar triangles, or using binary-search techniques. The single clipping
  490. plane would be specified to be somewhere in front of Z==0. (And no, not
  491. quite as far as "focus" distance used in perspective transformation,
  492. viewing plane is not necessarily a clipping plane).
  493.  
  494. The function to clip polygons would be almost identical too. (By
  495. the way, we can indeed try writing generic line and polygon clipping
  496. functions performing it for both 2D screen boundaries and view plane).
  497.  
  498.  
  499.  
  500. Volume clipping.
  501. ----------------
  502. First of all what view volume is? This is the set of all points in
  503. the "world" space which can appear on screen under certain projection 
  504. method. For example if we are using just the parallel projection 
  505. (let's forget for a second about perspective) we may see that only 
  506. points from depicted below rectangular area would appear on the screen.
  507.  
  508.  
  509.                         |                |
  510.                         |                |
  511.                         |                |    * B
  512.                         |        * C     |
  513.              Screen     |        |       |
  514.              boundaries |        v       |
  515.                    -----I--------*-------I----- Viewing plane.
  516.  
  517.                             * A
  518.  
  519.  
  520.                               pic 4.11
  521.  
  522. Point A can't appear on screen as it is behind the viewing plane - it would
  523. be clipped by the algorithm described above in this chapter. point B on the
  524. other hand is in front of the viewing plane, so it would pass the first test
  525. but since it's projection onto the viewing plane won't fit the screen it would
  526. be clipped by 2-D screen boundaries clipping routines. Point C is lucky to be
  527. inside the view volume. The conclusion here is that by doing first viewing
  528. plane clipping and then screen boundaries clipping we actually performed
  529. volume clipping, that is we selected from space the set of all points that
  530. can be projected and then did actual projection (Yes, by passing to the
  531. rendering routines just X and Y of points and discarding Z we basically did
  532. parallel projection). Should this be changed somehow to accommodate
  533. perspective projection? after all by clipping against view plane we guarantee
  534. that there would be no points with Z==0. However the problem is that even
  535. having points close to the viewing plane is not very good. pic 4.12
  536.  
  537.  
  538.  
  539.  
  540.                                         *--->
  541.  
  542.                                         *------------->
  543.                                         *-------------------------->
  544.                                                                      A*- - ->
  545.                           -----I-----I-----
  546.  
  547.  
  548.  
  549.                                pic 4.12
  550.  
  551. By applying perspective transformation we increase the absolute values
  552. of coordinate components depending on inverse of it's distance to the viewer,
  553. so if Z==0 transforms into infinity numbers close to that transform into
  554. something bitsize of numbers stored in computers might not be able to handle,
  555. and no, we can't quite solve it by moving the clipping plane slightly forward,
  556. since there are still those nasty points which are slightly in front of the
  557. viewing plane but already have big absolute value of X or Y. (pic 4.12,
  558. point A). The overflow problem that may result from perspectively transforming
  559. this point is this: positive values may become negative, and if it would
  560. happen to just one point of two off-screen points representing a line we
  561. may actually see this line all across the screen instead of not seeing it
  562. at all.
  563.  
  564. The conclusion when using perspective transformation, it is better to apply
  565. it to the points we know would produce a valid result. And since what we
  566. ultimately want is to project to the screen we are coming back to the
  567. view volumes since those are exactly sets of points that would be
  568. projected inside the screen. Hence we do need to consider actual viewing
  569. volume for perspective projection.
  570.  
  571. What the view volume for perspective projection would look like?
  572. The way we modeled this transformation - rays of all visible points
  573. converge in viewer's eye. If we would cast back into space lines connecting
  574. the eye and the screen boundaries, we would obtain the pyramid marking points
  575. from space that would project onto screen edges. what's inside the
  576. pyramid would project inside the screen what's outside - outside the screen.
  577. adding the clipping plane somewhere in front of the viewer we are obtaining the
  578. view-volume for perspective projection, pic 4.13.
  579.  
  580.  
  581.                            \             /
  582.                             \           /
  583.                              \         /
  584.                               \       /
  585.                                \     /
  586.                           -----I\---/I-----
  587.                                  \ /
  588.                                   *
  589.  
  590.                                pic 4.13
  591.  
  592. The only problem - we now have to clip against planes which are
  593. directed almost arbitrary in space (the exact geometry of this view volume
  594. depends on the "focus" parameter - the distance between the viewer and the
  595. viewing plane (again, not quite the same as clipping plane). Although 
  596. conceptually easy to achieve clipping against arbitrary directed plane 
  597. would have higher complexity.
  598.  
  599. There is number of solutions one can consider: obvious one: indeed implement
  600. real volume clipping, although expansive we would be able to completely
  601. get rid of 2-D clipping routines which overall might be quite descent.
  602. Second: implement volume clipping with special kind of perspective view
  603. volume, the one having 90' angle. The reason can be seen from the pic 4.14:
  604.  
  605.  
  606.                        \                     /
  607.                          \                 /
  608.                     x=-z   \             /   x=z
  609.                              \         /
  610.                           ----I\-----/I-----
  611.                                  \ /
  612.                                   *
  613.  
  614.                                pic 4.14
  615.  
  616. Planes composing this perspective view volume have pretty simple equations:
  617. x==z , y==z, x==-z and y==-z clipping against those is way easier then
  618. against arbitrary directed planes. The method however we would discuss is a
  619. bit different, that is, we would not do clipping at all, to be more exact we
  620. would only throw away polygons which are for sure outside the view volume and
  621. leave those even partially inside to be further clipped against screen
  622. boundaries after being projected. ( Clipping against viewing plane, is a
  623. sacred matter that one can hardly get rid of ) One should understand that this
  624. method works on assumption that there is no terribly big polygons around,
  625. since a one part of a really big polygon can be within the view volume whereas
  626. another can be both close to viewing plane and have really big absolute value
  627. of X or Y, just something we are trying to exclude from being perspectively
  628. projected.
  629.  
  630. How can one figure out whether a point is outside the pyramid with 90'
  631. angle? From the pic 4.14 we can see that parts of the space separated
  632. by Z==X and Z==-X planes have obvious relationships among X and Z of
  633. every point, if Z<X or Z<-X point is for sure outside this area. it
  634. should be realized we can't quite extend this scheme onto polygons by 
  635. saying if all points of a polygon are outside it is outside also, 
  636. example is a polygon AB on the pic 4.15, it is clear that although 
  637. both points composing it are outside there supposed to be some part
  638. of this polygon inside the view volume.
  639.  
  640.  
  641.                                   ^ Z
  642.                                   |
  643.                        \          |          /
  644.                          \   Z>-X | Z>X    /
  645.                            \      |      /
  646.                      A *---------------------* B
  647.                                \  |  /
  648.                           Z<-X   \ /   Z<X
  649.                     --------------*-----------------> X
  650.  
  651.                                pic 4.15
  652.  
  653.  
  654. We would make decisions, on the other hand, using notion of polygon's 
  655. extends. pic 4.16 Extend is a cube completely enclosing within itself 
  656. certain polygon. So coordinates of extend planes are that of maximum and 
  657. minimum among the polygon vertices along all axes.
  658.  
  659.                             xmin       xmax
  660.                             --------------  ymin
  661.                              |\\        |
  662.                              | \  \     |
  663.                              |   \    \ |
  664.                              |     \   /|
  665.                              |       \/ |
  666.                              |------------ ymax
  667.  
  668.                                  pic 4.16
  669.  
  670. This way by considering for example (xmin,zmax) point of the extend box we
  671. can make a decision whether polygon's extend is outside the x=z plane.
  672.  
  673.  
  674.  
  675.                                   ^ Z
  676.                                   |
  677.                        \          |          /
  678.                          \        |        /
  679.               (xmax,zmax)  \      |      /  (xmin,zmax)
  680.                      ----+   \    |    /  +----+
  681.                          |     \  |  /    |
  682.                        --+       \ /      +---
  683.                     --------------*-----------------> X
  684.                                      +-------+ (zmax)
  685.                                      |       |
  686.  
  687.  
  688.                                pic 4.17
  689.  
  690.  
  691. Let's list all the other cases:
  692.  
  693.                xmin > zmax
  694.                ymin > zmax
  695.               -xmax > zmax
  696.               -ymax > zmax
  697.  
  698. On the same stage we can check if the polygon is completely behind
  699. the view plane as well.
  700.  
  701.  
  702. int C_volume_clipping(register int *vxes,int number)
  703. {
  704.  int xmin,ymin,zmin,xmax,ymax,zmax;
  705.  int i;
  706.  
  707.  ymin=xmin=zmin=INT_MAX;
  708.  ymax=xmax=zmax=INT_MIN;                    /* initializing searching */
  709.  
  710.  for(i=0;i<number;i++)
  711.  {
  712.   if(*vxes>xmax) xmax=*vxes;
  713.   if(*vxes<xmin) xmin=*vxes;
  714.   vxes++;
  715.   if(*vxes>ymax) ymax=*vxes;
  716.   if(*vxes<ymin) ymin=*vxes;
  717.   vxes++;
  718.   if(*vxes>zmax) zmax=*vxes;
  719.   if(*vxes<zmin) zmin=*vxes;                /* searching max/min */
  720.   vxes++;
  721.  }
  722.  
  723.  if((zmax<xmin)||(zmax<ymin)||(zmax<-xmax)||
  724.    (zmax<-ymax)||(zmax<C_plane))
  725.   return(0);
  726.  else
  727.   if(zmin<C_plane) return(-1);              /* behind clipping plane */
  728.   else return(1);
  729. }
  730.  
  731.  
  732. It should be realized that, extend testing is approximate, there
  733. might be polygons outside the view volume whose extends are partly 
  734. inside, but since we are doing clipping to screen boundaries 
  735. afterwards they would eventually be taken care of. Besides, clipping 
  736. view volume is a pyramid with 90' angle, real view volume on the other 
  737. hand depends on the perspective transformation formula, and would 
  738. likely have angle less then 90'. And again, there should be no very 
  739. big polygons, since we are doing "full element" volume clipping.
  740.  
  741.                                      * * *